package cn.arnold.java8newfuture.optional;

import cn.arnold.java8newfuture.User;
import org.junit.Test;

import java.util.Optional;

/**
 * @Author Arnold
 * @Desc TODO
 **/
public class Demo1 {

    public static void main(String[] args) {
        filterTest();
    }

    /**
     * 创建一个空的Option实例
     * 尝试访问 emptyOpt 变量的值会导致 NoSuchElementException。
     */
    public static void emptyCreate(){
        Optional<User> emptyOpt = Optional.empty();
        emptyOpt.get(); // NoSuchElementException
    }

    /**
     * of()方法创建包含值的 Optional
     * 如果你把 null 值作为参数传递进去，of() 方法会抛出 NullPointerException
     */
    public static void ofCreate(){
        User user = new User();
        user = null;
        Optional<User> ofOpt = Optional.of(user);
        ofOpt.get(); // NullPointerException
    }

    /**
     * ofNullable()方法创建包含值的 Optional
     * 如果对象即可能是 null 也可能是非 null，你就应该使用 ofNullable() 方法
     */
    public static void ofNullableCreate(){
        User user = new User();
        user = null;
        Optional<User> ofOpt = Optional.ofNullable(user);
        ofOpt.get();
    }


    public static void getValueofOpt(){
        User user = new User();
        user.setAdress("湖北武汉");
        user.setName("melon");
        User user2 = null;
        Optional<User> userOpt = Optional.ofNullable(user2);
        User userGet = userOpt.get();
        System.out.println(userGet); // User(name=melon, adress=湖北武汉)
        System.out.println(userGet.getAdress()); // 湖北武汉
        System.out.println(userGet.getName()); // melon

    }

    /******************************************************/

    /**
     *  orElse():如果有值则返回该值，否则返回传递给它的参数值
     */
    public static void orElseTest(){
        User user1 = null;
        User user2 = new User("melon","湖北武汉"); // 备胎
        User userOpt = Optional.ofNullable(user1).orElse(user2); //user1为null,则返回user2
        System.out.println(userOpt);
        User user3 = new User("arnold","山东东营");
        User uesrOpt2 = Optional.ofNullable(user3).orElse(user2); //user2不为null,则返回user2
        System.out.println(uesrOpt2);
    }

    /**
     * map() 对值应用(调用)作为参数的函数，然后将返回的值包装在 Optional 中。
     * 这就使对返回值进行链试调用的操作成为可能 —— 这里的下一环就是 orElse()。
     */
    public static void mapTest(){
        User user = new User("melon","湖北武汉");
        //返回user的姓名
        String name = Optional.ofNullable(user).map(u -> u.getName()).orElse("defaul");
        System.out.println(name); // melon
    }

    /**
     * flatMap() 也需要函数作为参数，并对值调用这个函数，然后直接返回结果
     * 对 User 的 Optional 对象调用 flatMap() 时，用它作为参数。其返回的值是解除包装的 String 值：
     */
    public static void flatMapTest(){
        User user = new User("melon","湖北武汉");
        //返回user的姓名
        String postion = Optional.ofNullable(user).flatMap(u -> u.getPostion()).orElse("default");
        System.out.println(postion); // default
    }

       /**
     *filter() 接受一个 Predicate 参数，返回测试结果为 true 的值。如果测试结果为 false，会返回一个空的 Optional。
     */
    public static void filterTest(){
        User user = new User("melon","湖北武汉");
        // 根据地址是否在湖北来拒绝用户
        Optional<User> userOpt = Optional.ofNullable(user).filter(u -> u.getAdress() != null && u.getAdress().contains("湖北"));
        Optional<User> userOpt2 = Optional.ofNullable(user).filter(u -> u.getAdress() != null && u.getAdress().contains("山东"));
        System.out.println(userOpt); // Optional[User(name=melon, adress=湖北武汉, postion=Optional.empty)]
        System.out.println(userOpt2); // Optional.empty
    }

    public static void checkNPE(User user){
        String isocode = Optional.ofNullable(user).map(u -> u.getCountry()).map(a -> a.getIsocode()).orElse("default");


    }
}
